package com.ruoyi.security.service.craw.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.security.constant.ApiConstant;
import com.ruoyi.security.enums.SecurityNodeEnum;
import com.ruoyi.security.response.SecurityResponse;
import com.ruoyi.security.service.craw.ICrawSecurityService;
import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

/**
 * @author yeoman
 * @date 2025/4/30 18:19
 * @description
 */
@Slf4j
@Service
@SuppressWarnings("all")
public class CrawSecurityServiceImpl implements ICrawSecurityService {

    @Resource
    private ChromeDriver chromeDriver;

    @Override
    public List<SecurityResponse> crawList(String node) {
        List<SecurityResponse> securityList = Lists.newArrayList();
        Map<String, Object> urlVariables = Maps.newHashMap();
        urlVariables.put("page", 1);
        urlVariables.put("num", 100);
        // 按照代码排序
        urlVariables.put("sort", "symbol");
        // 升序 1 降序 0
        urlVariables.put("asc", "1");
        // 节点
        urlVariables.put("node", node);
        while (true) {
            log.info("【{}】开始爬取第{}页数据", SecurityNodeEnum.getDesc(node), urlVariables.get("page"));
            try {
                // 休眠，防止被封IP
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            String response = HttpUtils.sendGet(ApiConstant.SECURITY_LIST_URL, urlVariables);
            List<SecurityResponse> list = JSON.parseArray(response, SecurityResponse.class);
            if (CollectionUtils.isEmpty(list)) {
                break;
            }
            securityList.addAll(list);
            urlVariables.put("page", Integer.parseInt(urlVariables.get("page").toString()) + 1);
        }
        log.info("【{}】数据爬取完成，共{}条", SecurityNodeEnum.getDesc(node), securityList.size());
        return securityList;
    }

    @Override
    public SecurityResponse craw(String symbol) {
        return doCraw(symbol);
    }

    public SecurityResponse doCraw(String symbol) {
        SecurityResponse securityResponse = new SecurityResponse();
        chromeDriver.get(String.format(ApiConstant.SECURITY_DETAIL_URL, symbol));
        // 名称
        String name = chromeDriver.findElement(By.xpath("//*[@id=\"stockName\"]/i")).getText();
        // 最新价
        String price = chromeDriver.findElement(By.xpath("//*[@id=\"price\"]")).getText();
        // 涨跌额
        String change = chromeDriver.findElement(By.xpath("//*[@id=\"change\"]")).getText();
        // 涨跌幅 %
        String changepercent = chromeDriver.findElement(By.xpath("//*[@id=\"changeP\"]")).getText();
        // 涨停
        String limitUp = chromeDriver.findElement(By.xpath("//*[@id=\"ud_limie\"]/div[1]")).getText();
        // 跌停
        String limitDown = chromeDriver.findElement(By.xpath("//*[@id=\"ud_limie\"]/div[2]")).getText();
        // 时间
        String time = chromeDriver.findElement(By.xpath("//*[@id=\"hqTime\"]")).getText();
        // 昨收
        String preclose = chromeDriver.findElement(By.xpath("//*[@id=\"hqDetails\"]/table/tbody/tr[4]/td[1]")).getText();
        // 开盘价
        String open = chromeDriver.findElement(By.xpath("//*[@id=\"hqDetails\"]/table/tbody/tr[1]/td[1]")).getText();
        // 最高价
        String high = chromeDriver.findElement(By.xpath("//*[@id=\"hqDetails\"]/table/tbody/tr[2]/td[1]")).getText();
        // 最低价
        String low = chromeDriver.findElement(By.xpath("//*[@id=\"hqDetails\"]/table/tbody/tr[3]/td[1]")).getText();
        // 成交量
        String volume = chromeDriver.findElement(By.xpath("//*[@id=\"hqDetails\"]/table/tbody/tr[1]/td[2]")).getText();
        // 成交额
        String turnover = chromeDriver.findElement(By.xpath("//*[@id=\"hqDetails\"]/table/tbody/tr[2]/td[2]")).getText();
        // 总市值
        String totalMarketValue = chromeDriver.findElement(By.xpath("//*[@id=\"hqDetails\"]/table/tbody/tr[3]/td[2]")).getText();
        // 总股本
        String totalVolume = chromeDriver.findElement(By.xpath("//*[@id=\"hqDetails\"]/table/tbody/tr[5]/td[1]")).getText();
        // 流通市值
        String circulatingMarketValue = chromeDriver.findElement(By.xpath("//*[@id=\"hqDetails\"]/table/tbody/tr[4]/td[2]")).getText();
        // 流通股本
        String circulatingVolume = chromeDriver.findElement(By.xpath("//*[@id=\"hqDetails\"]/table/tbody/tr[5]/td[2]")).getText();
        // 振幅 %
        String amplitude = chromeDriver.findElement(By.xpath("//*[@id=\"hqDetails\"]/table/tbody/tr[1]/td[3]")).getText();
        // 换手率 %
        String turnoverRate = chromeDriver.findElement(By.xpath("//*[@id=\"hqDetails\"]/table/tbody/tr[2]/td[3]")).getText();
        // 市净率
        String pbRatio = chromeDriver.findElement(By.xpath("//*[@id=\"hqDetails\"]/table/tbody/tr[3]/td[3]")).getText();
        // 市盈率(动)
        String peRatioTtm = chromeDriver.findElement(By.xpath("//*[@id=\"hqDetails\"]/table/tbody/tr[4]/td[3]")).getText();

        securityResponse.setName(name);
        securityResponse.setTrade(price);
        securityResponse.setPricechange(change);
        securityResponse.setChangepercent(changepercent.replace("%", ""));
        securityResponse.setLimitUp(limitUp.replace("涨停：", ""));
        securityResponse.setLimitDown(limitDown.replace("跌停：", ""));
        securityResponse.setTime(time);
        securityResponse.setSettlement(preclose);
        securityResponse.setOpen(open);
        securityResponse.setHigh(high);
        securityResponse.setLow(low);
        // 成交量，单位转为手（万手转手）
        String volumeInHands = convertVolumeToHands(volume);
        securityResponse.setVolume(volumeInHands);
        // 成交额，单位转为万元（亿元转万元）
        String turnoverInWanYuan = convertTurnoverToWanYuan(turnover);
        securityResponse.setAmount(turnoverInWanYuan);
        securityResponse.setTotalMarketValue(totalMarketValue);
        securityResponse.setTotalVolume(totalVolume);
        securityResponse.setCirculatingMarketValue(circulatingMarketValue);
        securityResponse.setCirculatingVolume(circulatingVolume);
        securityResponse.setAmplitude(amplitude.replace("%", ""));
        securityResponse.setTurnoverRate(turnoverRate.replace("%", ""));
        securityResponse.setPbRatio(pbRatio);
        securityResponse.setPeRatioTtm(peRatioTtm);
        return securityResponse;
    }

    /**
     * 将成交量从万手转换为手
     * @param volume 成交量字符串，可能包含"万手"、"手"等单位
     * @return 转换后的手数
     */
    private String convertVolumeToHands(String volume) {
        if (volume == null || volume.trim().isEmpty()) {
            return "0";
        }
        
        try {
            // 移除所有空格
            String cleanVolume = volume.replaceAll("\\s+", "");
            
            // 如果包含"千万手"，转换为手
            if (cleanVolume.contains("千万手")) {
                String numberStr = cleanVolume.replace("千万手", "");
                double number = Double.parseDouble(numberStr);
                // 千万手转手：乘以10,000,000
                long hands = Math.round(number * 10000000);
                return String.valueOf(hands);
            }
            // 如果包含"万手"，转换为手
            else if (cleanVolume.contains("万手")) {
                String numberStr = cleanVolume.replace("万手", "");
                double number = Double.parseDouble(numberStr);
                // 万手转手：乘以10000
                long hands = Math.round(number * 10000);
                return String.valueOf(hands);
            }
            // 如果包含"手"，直接返回数字部分
            else if (cleanVolume.contains("手")) {
                return cleanVolume.replace("手", "");
            }
            // 如果只是数字，直接返回
            else {
                return cleanVolume;
            }
        } catch (NumberFormatException e) {
            log.warn("成交量格式转换失败：{}", volume, e);
            return "0";
        }
    }

    /**
     * 将成交额从亿元转换为万元
     * @param turnover 成交额字符串，可能包含"亿元"、"万元"等单位
     * @return 转换后的万元数
     */
    private String convertTurnoverToWanYuan(String turnover) {
        if (turnover == null || turnover.trim().isEmpty()) {
            return "0";
        }
        
        try {
            // 移除所有空格
            String cleanTurnover = turnover.replaceAll("\\s+", "");
            
            // 如果包含"亿元"，转换为万元
            if (cleanTurnover.contains("亿元")) {
                String numberStr = cleanTurnover.replace("亿元", "");
                double number = Double.parseDouble(numberStr);
                // 亿元转万元：乘以10000
                long wanYuan = Math.round(number * 10000);
                return String.valueOf(wanYuan);
            }
            // 如果包含"万元"，直接返回数字部分
            else if (cleanTurnover.contains("万元")) {
                return cleanTurnover.replace("万元", "");
            }
            // 如果只是数字，直接返回
            else {
                return cleanTurnover;
            }
        } catch (NumberFormatException e) {
            log.warn("成交额格式转换失败：{}", turnover, e);
            return "0";
        }
    }
}
